Sprint 2 — Revised onboarding becomes canonical#75
Conversation
Goal Packet v2.0 format. Single-mission contract for Codex. Mission: refactor RevisedOnboardingPage to drive the AGM-based revised onboarding flow (getAGMCandidates / getRevisedOnboardingData / applyStaffHires / applyScoutingHire / completeRevisedOnboarding) instead of the Day-One worker surface it currently uses. Then decide what to do with the orphaned Day-One worker methods. Read-first, allowed-write, protected scope, non-negotiables, milestone loop, validation loop, evaluator-visible proof, pause conditions, done criteria, and final report all encoded inline so the slash command can stay thin. Companion to Sprint 1 cleanup (PR #74). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The `/onboarding` route now loads the three fixed AGM candidates (Marcus Chen, Walter Kowalski, Elena Vargas) through `getAGMCandidates`, hydrates the chosen AGM via `getRevisedOnboardingData`, walks the sim-core `REVISED_CHAPTER_ORDER` end-to-end, applies coaching hires via `applyStaffHires`, applies the scouting director via `applyScoutingHire`, completes via `completeRevisedOnboarding`, then exports the snapshot and persists it through the existing IndexedDB save path before navigating to `/dashboard`. Component touch-ups: - AssessmentPanel: accepts revised chapter IDs alongside legacy ones, reusing the same chapter views. - ChapterProgress: accepts the revised chapter-order labels. The test for the route was rewritten test-first and now covers AGM selection, the staff-hiring step calling `applyStaffHires`, the scouting-hiring step calling `applyScoutingHire`, and the completion step calling `completeRevisedOnboarding`. Save schema stays at v33. Sim-core onboarding modules untouched. Co-Authored-By: Codex GPT-5 <noreply@openai.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The Day-One web worker methods (getDayOneSession, advanceDayOneIntro,
chooseDayOneAGM, advanceDayOneOrgReview, setDayOneSeasonGoal,
setDayOneBudgetAllocation, setDayOneOpeningPlan,
setDayOneDevelopmentPlan, resolveDayOneCrisis, finishDayOne) had no
remaining UI callers after /onboarding switched to the AGM-based
revised flow.
Removed from:
- apps/web/src/workers/sim.worker.onboarding.ts (exported wrappers)
- apps/web/src/workers/sim.worker.ts (onboardingApi Comlink map)
- apps/web/src/shared/hooks/useWorker.ts (callbacks + mutationMethods)
The protected sim-core source at packages/sim-core/src/onboarding/dayOne.ts
is left untouched per GOAL.md scope rules. Any future code that wants
Day-One semantics can reach it through a new worker wrapper.
Grep evidence after removal:
rg -n "getDayOneSession|advanceDayOneIntro|chooseDayOneAGM|advanceDayOneOrgReview|setDayOneSeasonGoal|setDayOneBudgetAllocation|setDayOneOpeningPlan|setDayOneDevelopmentPlan|resolveDayOneCrisis|finishDayOne" apps/web/src
returns no output.
sim.worker.onboarding.test.ts was rewritten to exercise the revised
AGM worker API in place of the removed Day-One paths.
Co-Authored-By: Codex GPT-5 <noreply@openai.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Hard-reloads on nested routes (e.g. /MBD/dashboard) previously failed with: "The server is configured with a public base URL of /MBD/ - did you mean to visit /MBD/dashboard instead?". Vite served the right index.html, but BrowserRouter had no basename and so could not match the path against the route table. This is the pause condition flagged in Sprint 2's first run: RevisedOnboardingPage worked end-to-end and IndexedDB saved cleanly, but a hard reload at /dashboard surfaced this pre-existing routing gap. Fix: derive the basename from import.meta.env.BASE_URL (which Vite statically injects from `base: '/MBD/'`), strip the trailing slash so react-router accepts it, and pass it to BrowserRouter. The cast around import.meta matches the existing pattern in TeamLogo because the web tsconfig does not currently include vite/client types. After this change a hard reload at /MBD/dashboard: - Returns 200 text/html from the dev server (no Vite base-URL error) - Resolves through react-router's basename strip into the /dashboard route - Renders the dashboard when a save is initialized, or redirects to Save Hub via the AppLayout uninitialized-state guard Verified via: - pnpm typecheck (clean) - pnpm --filter @mbd/web test src/app (28 tests passing) - pnpm --filter @mbd/web dev + browser navigation to /MBD/dashboard Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…moke screenshots Captures the milestone-by-milestone audit trail Codex produced during Sprint 2, the final Done-When-satisfied status report (updated after the BrowserRouter basename fix unblocked the hard-reload pause), and nine browser-smoke screenshots covering AGM selection, every revised chapter, completion, dashboard, and reload behavior. Files: - .logs/goal-progress.md - STATUS.md - apps/web/docs/screenshots/sprint-2/01-save-hub-setup.png - apps/web/docs/screenshots/sprint-2/02-agm-selection.png - apps/web/docs/screenshots/sprint-2/03-owner-office.png - apps/web/docs/screenshots/sprint-2/04-staff-hiring.png - apps/web/docs/screenshots/sprint-2/05-scout-hiring.png - apps/web/docs/screenshots/sprint-2/06-completion.png - apps/web/docs/screenshots/sprint-2/07-dashboard-after-completion.png - apps/web/docs/screenshots/sprint-2/08-dashboard-after-reload.png (pre-fix, kept as historical evidence) - apps/web/docs/screenshots/sprint-2/09-dashboard-after-savehub-reload-continue.png Co-Authored-By: Codex GPT-5 <noreply@openai.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 61718ed1e5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| default: | ||
| return null; |
There was a problem hiding this comment.
Mark Day One complete before exporting
When this revised flow replaces the old finishDayOne() path, completion only calls completeRevisedOnboarding before exporting the snapshot; that worker mutation sets franchise.onboarding.welcomeBriefingSeen but leaves franchise.dayOne at the new-game initial pending/currentStep values. The saved game is then written on the next line with contradictory onboarding state even though the user is sent to the dashboard, so please sync/mark the Day One fields complete before exporting.
Useful? React with 👍 / 👎.
* docs(goal): add Sprint 3 mission contract — News inbox Goal Packet v2.0 format. Single-mission contract for Codex. Mission: build a /news route that surfaces the worker-backed news feed (getNews / markNewsRead) the audit found unwired. Includes filter UI, mark-read on view, Sidebar nav entry, and an unread badge in TopBar. Read-first, allowed-write, protected scope, non-negotiables, milestone loop, validation loop, evaluator-visible proof, pause conditions, done criteria, and final report all encoded inline so the slash command can stay thin. Builds on Sprint 1 cleanup (PR #74) and Sprint 2 revised onboarding canonicalization (PR #75), both merged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(news): add /news inbox surfacing worker-backed news feed The audit found getNews(limit?) and markNewsRead(newsId) exposed in useWorker() and powered by sim-core/narrative/newsFeed.ts, but no UI consumed them. SettingsPage showed the unread count, full stop. This adds: - /news route lazy-loaded under AppLayout, wrapped in RouteErrorBoundary like every other feature route. - NewsPage list rendering: headline, body excerpt, category badge, priority indicator, optional tag chip, timestamp (Season X · Day Y or Now), related team chips. Read items have a clear visual treatment. - Filters: All / Unread toggle plus a category multi-select chip group. Filtering happens client-side over the worker's getNews(100) result. - Mark-read on item open: calls markNewsRead(id), persists the active save through the existing IndexedDB save path, decrements the in-session unread count. - Mobile-survivable at 375x667 — no horizontal overflow. - Loading skeleton, empty-state panel, and error toast for worker failures. - A small newsEvents helper module dispatches a "news-read" event so the TopBar unread chip can react across components without prop threading. Tests: NewsPage.test.tsx (4 tests) covers list render, filter behavior, mark-read flow, and worker mock surface. Schema stays at v33. No sim-core or contracts edits. Co-Authored-By: Codex GPT-5 <noreply@openai.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(layout): add News nav entry + unread badge in TopBar - Sidebar: new NavItem { to: '/news', label: 'News', icon: <Inbox /> }. Newspaper icon stays with Press Room. Sidebar.test asserts the entry renders. - TopBar: new unread chip that subscribes to news-read events and refetches worker getNews() to recompute the count after every read. Decrements as the user reads items. Match the existing TopBar density (small chip, no emoji, lucide-only). A new TopBar.test.tsx covers the chip render, the count reflecting the worker mock, and the post-read recompute. Co-Authored-By: Codex GPT-5 <noreply@openai.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(news): Sprint 3 status report, progress log, and browser-smoke screenshots Captures the milestone-by-milestone audit trail Codex produced during Sprint 3, the final Sprint-3-complete status report (reframed to distinguish the news inbox feature — which fully shipped — from the hard-reload state-hydration issue, which is pre-existing app-wide behavior that affects every in-game route and is now queued as Sprint 3.5), and six browser-smoke screenshots: - 01-dashboard-after-month.png Day 31 save context - 02-news-inbox-unread.png /MBD/news list with worker news - 03-news-category-filter.png Trade-category filter applied - 04-news-item-read.png Read state + TopBar chip decrement - 05-news-mobile-375.png 375x667 viewport, no overflow - 06-news-hard-reload-blocked.png pre-existing app-wide behavior (documented, not a Sprint 3 regression) IndexedDB save-state proof from save-slot-2: unread 580 -> 579 after read and survives reload at the data layer (only the routing redirect to Save Hub masks it visually). Co-Authored-By: Codex GPT-5 <noreply@openai.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Code <noreply@anthropic.com> Co-authored-by: Codex GPT-5 <noreply@openai.com>
Summary
Sprint 2 ships the AGM-based revised onboarding flow as the canonical
/onboardingexperience and removes the orphaned Day-One web worker surface./onboardingloads three fixed AGM candidates (Marcus Chen, Walter Kowalski, Elena Vargas), hydrates the selected AGM viagetRevisedOnboardingData, walksREVISED_CHAPTER_ORDER, applies staff and scouting hires through the revised worker mutations, completes throughcompleteRevisedOnboarding, exports the snapshot, and saves via the existing IndexedDB save path.getDayOneSession,advanceDayOneIntro,chooseDayOneAGM,advanceDayOneOrgReview,setDayOneSeasonGoal,setDayOneBudgetAllocation,setDayOneOpeningPlan,setDayOneDevelopmentPlan,resolveDayOneCrisis,finishDayOnedeleted fromuseWorker.ts,sim.worker.ts, andsim.worker.onboarding.ts. Grep confirms zero remaining callers inapps/web/src. Protectedpackages/sim-core/src/onboarding/dayOne.tsis untouched.BrowserRouternow setsbasenamefromimport.meta.env.BASE_URL, so reloads at/MBD/dashboardand other nested routes survive Vite's/MBD/public base. This unblocked the pause condition Codex flagged in the first run.Verification
Schema stays at v33. No new dependencies. Determinism preserved. Save flow unchanged.
Browser smoke (screenshots under
apps/web/docs/screenshots/sprint-2/):applyStaffHires)applyScoutingHire)IndexedDB save after completion:
schemaVersion: 33,snapshot.schemaVersion: 33,assistantGMId: marcus_chen,welcomeBriefingSeen: true.Day-One decision
Removed, with grep evidence in
STATUS.md. Sim-core'sdayOne.tssurvives — only the web worker bridge to it was deleted.How the work was sliced
5 commits on
goal/sprint-2-revised-onboarding:docs(goal):— Sprint 2 mission contract (Goal Packet v2.0)feat(onboarding):—/onboardingroute refactor to AGM-based revised flowrefactor(worker):— Day-One onboarding surface removalfix(app):— BrowserRouter basename for hard-reload survivaldocs(onboarding):— STATUS.md +.logs/goal-progress.md+ 9 browser-smoke screenshotsProcess
App.tsxwas outside the GOAL.md allowed write scope.Test plan
/MBD/dashboardworks without Vite's public-base errorapplyStaffHiresandapplyScoutingHirecalled at correct stepsschemaVersion: 33apps/web/docs/screenshots/sprint-2/to confirm UX still matches design intent🤖 Generated with Claude Code (review/ops) and Codex GPT-5 (build).